import numpy as np
from scipy import integrate
from deprecated.sphinx import deprecated


class Measurement:
    def __init__(self):
        self.losses = []
        self.preds = []

    @staticmethod
    def AILoss(x, ypred, ytrue, alpha=0):
        def function(y1):
            """ 考虑误差指数衰减
            :param y1:
            :return:
            """
            k = 0
            b = y1
            f = lambda t: 10 * np.exp(alpha * (t - ytrue)) * np.abs(k * t + b) / ytrue
            return f

        @deprecated(version="0.0.0", reason="等同于function")
        def function_1(y1):
            """ 不考虑误差指数衰减
            :param y1: 第一个点的y值
            :return:
            """
            k = 0
            b = y1
            f = lambda t: 10 * np.abs(k * t + b) / ytrue
            return f

        if x.shape[0] <= 1:
            return np.inf

        total_loss = 0
        for i in range(1, x.shape[0]):
            x1, x2 = x[i - 1], x[i]
            y1, y2 = ypred[i - 1] - ytrue, ypred[i] - ytrue

            if x1 > x2:
                return np.inf
            if x1 == x2:
                continue
            total_loss += integrate.quad(function(y1), x1, x2)[0]
        return total_loss

    @staticmethod
    def prepare_x_y(state):
        actions = state.actions
        ytrue = state.get_trace_ytrue()
        all_pred = state.get_trace_all_preds()
        times = state.get_trace_times()
        time_subseq = []
        pred_subseq = []
        for index in actions:
            time_subseq.append(times[index])
            pred_subseq.append(all_pred[index])
        time_subseq = np.array(time_subseq)
        pred_subseq = np.array(pred_subseq)
        return time_subseq, pred_subseq, ytrue

    def collect_result(self, loss, length):
        self.losses.append(loss)
        self.preds.append(length)

    def display_result(self):
        print(self.losses)
        print(self.preds)
        print(len(self.losses), len(self.preds))
        print(sum(self.losses)/len(self.losses), sum(self.preds)/len(self.preds))